export default class ShapeGeo {
	constructor(pathData = []) {
		this.pathData = pathData;
		// 地理数据
		this.geoData = [];
		// 三角形 集合
		this.triangles = [];
		// 点 集合
		this.vertices = [];
		this.parsePath();
		this.update();
	}
	
	update() {
		this.vertices = [];
		this.triangles = [];
		this.findTriangle(0);
		this.updateVertices();
	}
	
	parsePath() {
		this.geoData = [];
		const { pathData, geoData } = this;
		for (let i = 0; i < pathData.length; i += 2) {
			geoData.push({ x: pathData[i], y: pathData[i + 1] });
		}
	}
	
	// 查找三角形
	findTriangle(i) {
		const { geoData, triangles } = this;
		const len = geoData.length;
		if (geoData.length <= 3) {
			triangles.push([...geoData]);
		} else {
			// 循环查找
			const [i0, i1, i2] = [
				i % len,
				(i + 1) % len,
				(i + 2) % len
			];
			const triangle = [
				geoData[i0],
				geoData[i1],
				geoData[i2],
			];
			if (this.cross(triangle) > 0 && !this.includePoint(triangle)) {
				// 如果是一个符合条件的三角形则存入
				triangles.push(triangle);
				// 然后删掉该点
				geoData.splice(i1, 1);
			}
			this.findTriangle(i1);
		}
	}
	// 是否包含点
	includePoint(triangle) {
		for (let ele of this.geoData) {
			// 判断是否为三角形的某个顶点， 该点是否在其他三角形当中
			if (!triangle.include(ele) && this.inTriangle(ele, triangle)) {
				return true;
			}
		}
		return false;
	}
	// 判断是否在三角形中
	inTriangle(p0, triangle) {
		let inPoly = true;
		for (let i = 0; i < 3;i++) {
			const j = (i + 1) % 3;
			const [p1, p2] = [triangle[i], triangle[j]];
			// 如果在某条边的右侧
			if (this.cross([p0, p1, p2]) < 0) {
				inPoly = false;
				break;
			}
		}
		return inPoly;
	}
	// 判断交叉点
	cross([p0, p1, p2]) {
		const [ax, ay, bx, by] = [
			p1.x - p0.x,
			p1.y - p0.y,
			p2.x - p0.x,
			p2.y - p0.y
		];
		return ax * by - bx * ay;
	}
	// 基于三角形集合更新点集合
	updateVertices() {
		const arr = [];
		this.triangles.forEach(triangle => {
			for (let { x, y } of triangle) {
				arr.push(x, y);
			}
		});
		this.vertices = arr;
	}
}